package com.demo.alg.chapter15动态规划.最长递增子序列;

/**
 * 最长递增子序列问题的描述
设L=<a1,a2,…,an>是n个不同的实数的序列，L的递增子序列是这样一个子序列Lin=<aK1,ak2,…,akm>，其中k1<k2<…<km且aK1<ak2<…<akm。求最大的m值。

设长度为N的数组为{a0，a1, a2, ...an-1)，则假定以aj结尾的数组序列的最长递增子序列长度为L(j)，则L(j)={ max(L(i))+1, i<j且a[i]<a[j] }。也就是说，我们需要遍历在j之前的所有位置i(从0到j-1)，
找出满足条件a[i]<a[j]的L(i)，求出max(L(i))+1即为L(j)的值。最后，我们遍历所有的L(j)（从0到N-1），找出最大值即为最大递增子序列。时间复杂度为O(N^2)。

例如给定的数组为{5，6，7，1，2，8}，则L(0)=1, L(1)=2, L(2)=3, L(3)=1, L(4)=2, L(5)=4。所以该数组最长递增子序列长度为4，序列为{5，6，7，8}。算法代码如下：
 */
public class Dp05 {

	public static int lis(int arr[], int len)
	{
	    int longest[] = new int[len];
	    for (int i=0; i<len; i++)
	        longest[i] = 1;

	    for (int j=1; j<len; j++) {
	        for (int i=0; i<j; i++) {
	            if (arr[j]>arr[i] && longest[j]<longest[i]+1) { //注意longest[j]<longest[i]+1这个条件，不能省略。
	                longest[j] = longest[i] + 1; //计算以arr[j]结尾的序列的最长递增子序列长度
	            }
	        }
	    }

	    int max = 0;
	    for (int j=0; j<len; j++) {
	        if (longest[j] > max) max = longest[j];  //从longest[j]中找出最大值
	    }
	    return max;
	}

	public static void main(String[] args) {
		int arr[] = {5, 6, 7, 1, 2, 8, 9};
		int ret = Dp05.lis(arr, arr.length);
		System.out.println(ret);
	}

}
